<?php
/**
 * 支付宝支付
 * Created by PhpStorm.
 * User: phperstar
 * Date: 2019/12/03
 * Time: 09:51 AM
 */
namespace Util\AliPay;

use Mall\Framework\Core\ErrorCode;
Use Mall\Framework\Core\ResultWrapper;

use Util\AliPay\Sign;

class Pay extends Sign
{
    /**
     * 支付宝应用id
     */
    private $appid;

    /**
     * 应用私钥
     */
    private $rsaPrivateKey;

    /**
     * 微信支付异步通知地址
     */
    private $notifyUrl = URL_PROJECT.'/common/AliPayNotify/notify';

    /**
     * 公共的接口请求地址
     * @var string
     */
    private $gatewayUrl = 'https://openapi.alipay.com/gateway.do';


    public function __construct($appid, $rsaPrivateKeyFilePath,$rsaPrivateKey){
        $this->appid = $appid;
        $this->rsaPrivateKey = $rsaPrivateKey;
        parent::__construct($rsaPrivateKeyFilePath, $rsaPrivateKey);
    }

    /**
     * 统一收单交易创建接口
     * 官方文档地址: https://opendocs.alipay.com/apis/api_1/alipay.trade.create/
     */
    public function Pay($orderData, $app_auth_token = '', $alipay_public_key = '')
    {
        // 获取业务请求参数集合
        $return = self::getPayBizContent($orderData);
        if(!$return->isSuccess()){
            return ResultWrapper::fail($return->getData(), $return->getErrorCode());
        }
        $biz_content = $return->getData();

        // 公共请求参数
        $params = [
            'app_id' => $this->appid,
            'method' => 'alipay.trade.create',
            'format' => 'json',
            'charset' => 'UTF-8',
            'sign_type' => 'RSA2',
            'timestamp' => date("Y-m-d H:i:s"),
            'version' => '1.0',
            'notify_url'=> $this->notifyUrl,
        ];

        if(!empty($app_auth_token)){
            $params['app_auth_token']   = $app_auth_token;
            $params['app_private_key']  = $this->rsaPrivateKey;
            $params['alipay_public_key']  = $alipay_public_key;
        }

        $params['biz_content'] = $biz_content;

        ksort($params);

        // 生成签名
        $params['sign'] = parent::sign($params);
        foreach ($params as &$value) {
            $value = $this->characet($value, $params['charset']);
        }

        //系统参数放入GET请求串
        $requestUrl = $this->gatewayUrl . "?";
        unset($params['biz_content']);
        foreach ($params as $sysParamKey => $sysParamValue) {
            $requestUrl .= "$sysParamKey=" . urlencode($this->characet($sysParamValue, "UTF-8")) . "&";
        }
        $requestUrl = substr($requestUrl, 0, -1);

        $reponse = request($requestUrl,['biz_content' => $biz_content]);
        $return = self::commonReust($reponse, $params['method']);
        if(!$return->isSuccess()){
            return ResultWrapper::fail($return->getData(), $return->getErrorCode());
        }
        return ResultWrapper::success($return->getData());
    }


    /**
     * 业务参数
     * 请求字符编码必须是UTF-8
     */
    private function getPayBizContent($orderData)
    {
        $bizcontent = [
            'out_trade_no'   => $orderData['out_trade_no'], // 商户订单号
            'total_amount'   => $orderData['total_amount'], // 订单总金额，单位为元，精确到小数点后两位
            'subject'        => $orderData['subject'], // 商品的标题/交易标题/订单标题/订单关键字
            'buyer_id'       => $orderData['userId'], // 小程序支付必填，付款用户的支付宝 user_id
            'timeout_express'   => isset($orderData['timeout_express'])?$orderData['timeout_express']:'30m', // 最晚付款时间
            'passback_params' => urlencode($orderData['passback_params']), // 回调数据
            'product_code'    => 'FACE_TO_FACE_PAYMENT',
            /*'extend_params'   => [
                'sys_service_provider_id' => '2088141497908793', // 系统商编号,系统商签约协议的PID
                'food_order_type'  => $orderData['food_order_type'], // 点餐场景类型
            ],*/
        ];

        foreach ($bizcontent as $key => $value){
            if(empty($value)){
                return ResultWrapper::fail('业务参数'.$key.'为空值', ErrorCode::$paramError);
            }
        }

        return  ResultWrapper::success(json_encode($bizcontent, JSON_UNESCAPED_UNICODE));
    }

    /**
     * 统一收单交易退款接口
     * 官方文档地址: https://opendocs.alipay.com/apis/api_1/alipay.trade.refund
     */
    public function refund($orderData, $app_auth_token = '', $alipay_public_key = '')
    {
        // 获取业务请求参数集合
        $return = self::getPayRefundContent($orderData);
        if(!$return->isSuccess()){
            return ResultWrapper::fail($return->getData(), $return->getErrorCode());
        }
        $biz_content = $return->getData();

        // 公共请求参数
        $params = [
            'app_id' => $this->appid,
            'method' => 'alipay.trade.refund',
            'format' => 'json',
            'charset' => 'UTF-8',
            'sign_type' => 'RSA2',
            'timestamp' => date("Y-m-d H:i:s"),
            'version' => '1.0',
        ];

        if(!empty($app_auth_token)){
            $params['app_auth_token']   = $app_auth_token;
            $params['app_private_key']  = $this->rsaPrivateKey;
            $params['alipay_public_key']  = $alipay_public_key;
        }

        $params['biz_content'] = $biz_content;

        ksort($params);

        // 生成签名
        $params['sign'] = parent::sign($params);
        foreach ($params as &$value) {
            $value = $this->characet($value, $params['charset']);
        }

        //系统参数放入GET请求串
        $requestUrl = $this->gatewayUrl . "?";
        unset($params['biz_content']);
        foreach ($params as $sysParamKey => $sysParamValue) {
            $requestUrl .= "$sysParamKey=" . urlencode($this->characet($sysParamValue, "UTF-8")) . "&";
        }
        $requestUrl = substr($requestUrl, 0, -1);

        $reponse = request($requestUrl,['biz_content' => $biz_content]); V($reponse);
        $return = self::commonReust($reponse, $params['method']);
        if(!$return->isSuccess()){
            return ResultWrapper::fail($return->getData(), $return->getErrorCode());
        }
        return ResultWrapper::success($return->getData());
    }

    /**
     * 业务参数
     * 请求字符编码必须是UTF-8
     */
    private function getPayRefundContent($orderData)
    {
        $bizcontent = [
            'out_trade_no'   => $orderData['out_trade_no'], // 商户订单号
            'refund_amount'  => $orderData['refund_amount'], // 订单总金额，单位为元，精确到小数点后两位
        ];

        foreach ($bizcontent as $key => $value){
            if(empty($value)){
                return ResultWrapper::fail('业务参数'.$key.'为空值', ErrorCode::$paramError);
            }
        }

        return  ResultWrapper::success(json_encode($bizcontent, JSON_UNESCAPED_UNICODE));
    }


    /**
     * 外部商户APP唤起快捷SDK创建订单并支付
     * 官方文档地址: https://docs.open.alipay.com/api_1/alipay.trade.app.pay
     */
    public function appPay($orderData)
    {
        // 获取业务请求参数集合
        $return = self::getAppPayBizContent($orderData);
        if(!$return->isSuccess()){
            return ResultWrapper::fail($return->getData(), $return->getErrorCode());
        }
        $biz_content = $return->getData();

        // 公共请求参数
        $params = [
            'app_id' => $this->appid,
            'method' => 'alipay.trade.app.pay',
            'format' => 'json',
            'charset' => 'UTF-8',
            'sign_type' => 'RSA2',
            'timestamp' => date("Y-m-d H:i:s"),
            'version' => '1.0',
            'notify_url'=> $this->notifyUrl,
        ];

        $params['biz_content'] = $biz_content;

        ksort($params);

        // 生成签名
        $params['sign'] = self::sign($params);
        foreach ($params as &$value) {
            $value = $this->characet($value, $params['charset']);
        }
        $return = http_build_query($params);
        return ResultWrapper::success($return);
    }

    /**
     * 业务参数
     * 请求字符编码必须是UTF-8
     */
    private function getAppPayBizContent($orderData)
    {
        $bizcontent = [
            'subject'        => $orderData['subject'], // 商品的标题/交易标题/订单标题/订单关键字
            'out_trade_no'   => $orderData['out_trade_no'], // 商户网站唯一订单号
            'timeout_express'   => isset($orderData['timeout_express'])?$orderData['timeout_express']:'30m', // 最晚付款时间
            'total_amount'   => $orderData['total_amount'], // 订单总金额，单位为元，精确到小数点后两位
            'passback_params' => urlencode($orderData['passback_params']), // 回调数据
            'product_code'    => 'QUICK_MSECURITY_PAY',
        ];

        foreach ($bizcontent as $key => $value){
            if(empty($value)){
                return ResultWrapper::fail('业务参数'.$key.'为空值', ErrorCode::$paramError);
            }
        }

        return  ResultWrapper::success(json_encode($bizcontent, JSON_UNESCAPED_UNICODE));
    }


    /**
     * 统一的错误处理方法
     */
    public function commonReust($reponse, $methodName)
    {
        if($reponse['httpcode'] != 200){
            return ResultWrapper::fail('请求外部接口网络错误', ErrorCode::$apiNotResult);
        }

        $reponseContent = json_decode($reponse['content'], true);
        $response = $reponseContent[str_replace('.','_',$methodName).'_response'];
        if($response['code'] != 10000){
            return ResultWrapper::fail($response['msg'].$response['sub_msg'], $response['code']);
        }
        return ResultWrapper::success($response);
    }

}